package com.wanxi.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;



/**
 * @Author:Doteon
 * @createDate:2023/3/7
 * @version: 1.0
 */
@Configuration
@Slf4j
public class RabbitConfig {
    private static String TOPIC_EXCHANGE="wx.fuzhuang.topic";

    @Bean
    public Queue superAdminQueue(){
        log.info("superAdminQueue 实例化成功...");
        return new Queue("wx.fuzhuang.super_admin",true);
    }
    @Bean
    public Queue adminQueue(){
        log.info("adminQueue 实例化成功...");
        return new Queue("wx.fuzhuang.admin",true);
    }
    @Bean
    public Queue userQueue(){
        log.info("userQueue 实例化成功...");
        return new Queue("wx.fuzhuang.user",true);
    }

    @Bean
    TopicExchange wxFuzhuangTopicExchange() {
        // 如果rabbit 里没有这个exchange，则会创建一个
        log.info("Topic 实例化成功...,name={}",TOPIC_EXCHANGE);
        return new TopicExchange(TOPIC_EXCHANGE,true,false);
    }
    @Bean
    Binding superAdminQueue2WxFuzhuangTopic() {
        // 绑定队列到topic. 这里的routingKey是binding key.
        log.info(" superAdminQueue 绑定 Topic 成功");
        return BindingBuilder.bind(superAdminQueue()).to(wxFuzhuangTopicExchange()).with("wx.fuzhuang.#");
    }
    @Bean
    Binding adminQueue2WxFuzhuangTopic() {
        // 绑定队列到topic,这里的routingKey是binding key.
        log.info(" adminQueue 绑定 Topic 成功");
        return BindingBuilder.bind(adminQueue()).to(wxFuzhuangTopicExchange()).with("wx.fuzhuang.admin.*");
    }

    @Bean
    Binding userQueue2WxFuzhuangTopic() {
        // 绑定队列到topic,这里的routingKey是binding key.
        log.info(" userQueue 绑定 Topic 成功");
        return BindingBuilder.bind(userQueue()).to(wxFuzhuangTopicExchange()).with("wx.fuzhuang.user.*");
    }

    @Bean
    RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate=new RabbitTemplate(connectionFactory);
        //连接mq成功，但是发送到exchange失败或成功
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (correlationData==null){
                    log.debug("correlationData is null");
                }
                if(ack == false) {
                    log.error("消息发送到交换机失败，ack=false,进行入库处理,异常信息：{}",cause.toString());
                    // TODO:补充业务处理
                } else {
                    log.debug("ack,消息投递到exchange成功,msgId:{},准备入副本队列");
                    // TODO:补充业务逻辑
                }
            }
        });
        // 设置退回机制，的回调函数。
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                // 但是路由到queue失败,通过实现ReturnCallback接口，对回退消息进行重发处理
                // 成功到达了交换机且未到达队列才会触发回调函数（交换机存在，但找不到路由导致）
                log.error("消息发到队列失败，请检查交换机或路由.{}",returnedMessage);
                // 补充业务处理
            }
        });
        // 设置消息转换成json格式，这个配置不是必须
        rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter());
        // 设置应答时长
        rabbitTemplate.setReplyTimeout(6000);
        return rabbitTemplate;
    }
    @Bean
    public MessageConverter jackson2JsonMessageConverter() {
        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
        return jackson2JsonMessageConverter;
    }


}
